package com.stack.knowyouweb.controller;

import com.google.gson.Gson;
import com.stack.knowyoubase.constant.GlobalConst;
import com.stack.knowyoubean.bean.RepJson;
import com.stack.knowyoubean.bean.User;
import com.stack.knowyouservice.service.impl.UserServiceImpl;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


/**
 * 用户表所承担一些请求
 * 配置为单例，减少了cpu和内存的消耗，不涉及共享资源，线程安全（当存在共享资源，设为多例）
 * RestController=@controller+@reponsebody
 *
 * @author stack
 */
@RestController
@Scope("singleton")
@RequestMapping("/api")
public class UserController {

    /**
     * 通过事务管理实现了aop代理，采用了基于proxy接口的动态代理
     * 所以注入接口，实现方法增强
     */
    @Resource
    private UserServiceImpl userService;

    @Resource
    private Gson gson;

    @Resource
    private BCryptPasswordEncoder passwordEncoder;

    /**
     * ModelAttribute 可以作用在方法和参数上
     * 作用：在控制器方法执行前执行，可用于参数补齐（有返回值）
     * 执行一些操作（无返回值）
     * 进行用户信息查询，在查询时直接绑定参数返回
     * 用户信息更新是：进行一些没有包含在数据库字段的补齐保证数据库的完整性
     * 安全问题:账户入侵
     *
     * @param authentication 权限信息
     * @return 用户实体 user存入请求域中用于参数绑定
     */
    @ModelAttribute("user")
    public User findUser(Authentication authentication) {
        //当为注册和忘记密码时返回空
        if (authentication == null) {
            return null;
        } else {
            return userService.userInfo(authentication.getName());
        }
    }

    /**
     * ModelAttribute 与方法返回的参数进行绑定
     * 从服务端获取认证角色
     *
     * @param user 用户吗
     * @return 用户信息
     */
    @GetMapping("/user")
    public String userInfo(@ModelAttribute("user") User user, HttpSession session, HttpServletResponse response) {
        //安全校验（是否为认证账户）
        String userid = (String) session.getAttribute("userid");
        if (!userid.equals(String.valueOf(user.getUserid()))) {
            response.setStatus(403);
            return null;
        }
        //泛型集合，jdk1.8当使用时分配内存
        RepJson<User> repJson = new RepJson<>();
        repJson.setCode(GlobalConst.SUCCESS_CODE);
        repJson.setData(user);
        return gson.toJson(repJson);
    }


    /**
     * ModelAttribute 与方法返回的参数进行绑定进行用户未提交字段的补齐
     * 更新个人信息和密码
     *
     * @param user 用户
     * @return 更新成功的标记
     */
    @PutMapping("/user")
    public String userUpdate(@ModelAttribute("user") User user, String oldPassword, String newPassword, HttpSession session, HttpServletResponse response) {
        //安全校验（是否为认证账户）
        String userid = (String) session.getAttribute("userid");
        if (!userid.equals(String.valueOf(user.getUserid()))) {
            response.setStatus(403);
            return null;
        }

        RepJson<String> repJson = new RepJson<>();
        //是否更新密码的绑定
        if (oldPassword != null && newPassword != null) {
            //旧密码验证
            boolean matches = passwordEncoder.matches(oldPassword, user.getPassword());
            if (matches) {
                //密码加密更新字段
                user.setPassword(passwordEncoder.encode(newPassword));
            } else {
                repJson.setCode(GlobalConst.ERROR_CODE);
                repJson.setData(GlobalConst.ERROR_TYPE);
                repJson.setMsg("旧密码有误，不能修改");
                return gson.toJson(repJson);
            }
        }
        boolean update = userService.userUpdate(user);
        if (update) {
            repJson.setCode(GlobalConst.SUCCESS_CODE);
            repJson.setData(GlobalConst.SUCCESS_TYPE);
            repJson.setMsg("修改信息成功");
        } else {
            repJson.setCode(GlobalConst.SUCCESS_CODE);
            repJson.setData(GlobalConst.ERROR_TYPE);
            repJson.setMsg("修改信息失败");
        }
        return gson.toJson(repJson);
    }

    @PostMapping("/user/unLock")
    public String userUnLock(@RequestParam(required = true) String password, Authentication authentication) {
        User user = userService.userInfo(authentication.getName());
        boolean matches = passwordEncoder.matches(password, user.getPassword());
        RepJson<String> repJson = new RepJson<>();
        repJson.setCode(GlobalConst.SUCCESS_CODE);
        if (matches) {
            repJson.setData(GlobalConst.SUCCESS_TYPE);
            repJson.setMsg("解锁成功");
        } else {
            repJson.setData(GlobalConst.ERROR_TYPE);
            repJson.setMsg("密码错误");
        }
        return gson.toJson(repJson);
    }

    @PostMapping("/user/register")
    public String userRegister(Integer username, String password, String role, String email, String captcha, HttpSession session) {
        RepJson<String> repJson = new RepJson<>();
        String mailTarget= (String) session.getAttribute("mailTarget");
        //注意空指针异常
        if (username == 0 || StringUtils.isEmpty(password) || StringUtils.isEmpty(email) || StringUtils.isEmpty(mailTarget)||!mailTarget.equals(email)) {
            repJson.setCode(GlobalConst.ERROR_CODE);
            repJson.setMsg("注册信息有误，请重新获取验证码");
        } else {
            if (GlobalConst.TEACHER_ROLE.equals(role) || GlobalConst.STUDENT_ROLE.equals(role)) {
                String registerCaptCha = (String) session.getAttribute("registerCaptCha");
                if (StringUtils.isEmpty(registerCaptCha) || !captcha.equals(registerCaptCha)) {
                    repJson.setCode(GlobalConst.ERROR_CODE);
                    repJson.setMsg("验证码错误,请重新获取验证码");
                } else {
                    User user = new User();
                    user.setUserid(username);
                    user.setPassword(passwordEncoder.encode(password));
                    user.setRole(role);
                    user.setEmail(email);
                    boolean b = userService.userRegister(user);
                    if (b) {
                        repJson.setCode(GlobalConst.SUCCESS_CODE);
                        repJson.setMsg("注册成功");
                    } else {
                        repJson.setCode(GlobalConst.ERROR_CODE);
                        repJson.setMsg("账号已经存在，注册失败，请重新获取验证码");
                    }
                }
            } else {
                repJson.setCode(GlobalConst.ERROR_CODE);
                repJson.setMsg("注册信息有误，注册失败,请重新获取验证码");
            }
        }
        //移除session域信息
        session.removeAttribute("mailTarget");
        session.removeAttribute("registerCaptCha");
        return gson.toJson(repJson);
    }

    @PostMapping("/user/forgetPass")
    public String userForgetPass(String username, String password, String captcha, HttpSession session) {
        RepJson<String> repJson = new RepJson<>();
        //验证提交信息是否一致问题，解决获取验证码可以修改其他用户密码问题
        String verifyUsername= (String) session.getAttribute("username");
        //注意空指针异常
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || StringUtils.isEmpty(verifyUsername)||!verifyUsername.equals(username)) {
            repJson.setCode(GlobalConst.ERROR_CODE);
            repJson.setMsg("输入信息有误,请重新获取验证码");
        } else {
            String forgetPassCaptCha = (String) session.getAttribute("forgetPassCaptCha");
            if (StringUtils.isEmpty(forgetPassCaptCha) || !captcha.equals(forgetPassCaptCha)) {
                repJson.setCode(GlobalConst.ERROR_CODE);
                repJson.setMsg("验证码错误，请重新获取验证码");
            } else {
                boolean b = userService.userForgetPass(username, passwordEncoder.encode(password));
                if (b) {
                    repJson.setCode(GlobalConst.SUCCESS_CODE);
                    repJson.setMsg("修改密码成功");
                } else {
                    repJson.setCode(GlobalConst.ERROR_CODE);
                    repJson.setMsg("账号信息错误,请重新获取验证码");
                }
            }
        }
        //移除session域中信息
        session.removeAttribute("username");
        session.removeAttribute("forgetPassCaptCha");
        return gson.toJson(repJson);
    }


}
